package ttcamera.camera;

import java.io.ByteArrayOutputStream;
import java.io.IOException;

import ttcamera.common.TTCameraConstant;
import ttcamera.layout.ActivityCamera;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.ImageFormat;
import android.graphics.Matrix;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.YuvImage;
import android.hardware.Camera;
import android.hardware.Camera.CameraInfo;
import android.hardware.Camera.PreviewCallback;
import android.hardware.Camera.Size;
import android.util.Log;
import android.view.Display;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

public class Preview extends SurfaceView implements SurfaceHolder.Callback { // <1>

	public SurfaceHolder mHolder;
	public Camera camera;
	public Activity mMainActivity;
	private Context mContext;

	@SuppressWarnings("deprecation")
	public Preview(Context context) {
		super(context);
		Log.d("TAG", "New preview");
		mContext = context;
		// mHolder = null;
		mHolder = getHolder(); // <4>
		// mHolder.removeCallback(this);
		mHolder.addCallback(this); // <5>
		mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); // <6>

		if (TTCameraConstant.CAMERA_PREVIEW == 0)
			camera = Camera.open();
		else
			camera = Camera.open(CameraInfo.CAMERA_FACING_FRONT);

		Camera.Parameters p = camera.getParameters();
		p.setPictureFormat(PixelFormat.JPEG);
		p.setJpegQuality(50);
		camera.setParameters(p);
		// camera.setDisplayOrientation(90);
	}

	@Override
	public void surfaceCreated(SurfaceHolder holder) {
		try {
			camera.setPreviewDisplay(holder);
			camera.setPreviewCallback(previewCallBack);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public PreviewCallback previewCallBack = new PreviewCallback() {
		@SuppressLint("NewApi")
		public void onPreviewFrame(byte[] yuv420sp, Camera camera) {
			// DisplayMetrics dm = new DisplayMetrics();

			// ((Activity) mContext).getWindowManager().getDefaultDisplay()
			// .getMetrics(dm);
			// Log.d("TAG", "height : " + dm.heightPixels);
			// Log.d("TAG", "width : " + dm.widthPixels);
			// Camera.Parameters parameters = camera.getParameters();
			Preview.this.invalidate();
			Size previewSize = camera.getParameters().getPreviewSize();
			YuvImage yuvimage = new YuvImage(yuv420sp, ImageFormat.NV21,
					previewSize.width, previewSize.height, null);

			// YuvImage yuvimage = new YuvImage(yuv420sp, ImageFormat.NV21,
			// dm.widthPixels, dm.heightPixels, null);

			Display display = ((Activity) mContext).getWindowManager()
					.getDefaultDisplay();
			int rotate = 0;
			// int rotation =
			// mContext.getResources().getConfiguration().orientation;
			// Log.i("TAG", "screen rotation is " + rotation);
			// Log.i("TAG", "display rotation is " + display.getRotation());

			if (display.getRotation() == Surface.ROTATION_0)
				if (TTCameraConstant.CAMERA_PREVIEW == CameraInfo.CAMERA_FACING_FRONT)
					rotate = 270;
				else
					rotate = 90;
			else if (display.getRotation() == Surface.ROTATION_90)
				rotate = 0;
			else if (display.getRotation() == Surface.ROTATION_180)
				rotate = 90;
			else if (display.getRotation() == Surface.ROTATION_270)
				rotate = 180;

			Bitmap tmp = (Bitmap) rotateBitmap(yuvimage, rotate, new Rect(0, 0,
					previewSize.width, previewSize.height));
			ByteArrayOutputStream stream = new ByteArrayOutputStream();
			tmp.compress(Bitmap.CompressFormat.JPEG,
					TTCameraConstant.CAMERA_QUALITY, stream);
			byte[] jdata = stream.toByteArray();

			// ByteArrayOutputStream baos = new ByteArrayOutputStream();
			// yuvimage.compressToJpeg(new Rect(0, 0, previewSize.width,
			// previewSize.height), TTCameraConstant.CAMERA_QUALITY, baos);
			// byte[] jdata = baos.toByteArray();

			if (mMainActivity != null) {
				((ActivityCamera) mMainActivity).getBuffer(jdata);
			} else
				Log.d(TTCameraConstant.TAG, "mMainActivity is null");

		}
	};

	// Called when the holder is destroyed
	/*
	 * @Override public void surfaceDestroyed(SurfaceHolder holder) { // <14>
	 * super.surfaceDestroyed(holder); }
	 */

	// Called when holder has changed
	@Override
	public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { // <15>
		Log.d(TTCameraConstant.TAG, "surfaceChanged");
		try {
			Camera.Parameters parameters = camera.getParameters();

			Display display = ((Activity) mContext).getWindowManager()
					.getDefaultDisplay();

			int rotation = mContext.getResources().getConfiguration().orientation;
			// Log.i("TAG", "screen rotation is " + rotation);
			// Log.i("TAG", "display rotation is " + display.getRotation());

			if (display.getRotation() == Surface.ROTATION_0
					&& rotation == Configuration.ORIENTATION_PORTRAIT) {
				if (TTCameraConstant.CAMERA_PREVIEW == CameraInfo.CAMERA_FACING_FRONT) {
					parameters.setPreviewSize(h, w);
					parameters.setRotation(270);
					camera.setDisplayOrientation(90);
				} else {
					parameters.setPreviewSize(h, w);
					parameters.setRotation(270);
					camera.setDisplayOrientation(90);
				}

				Log.d("TAG", "Surface.ROTATION_0 - ORIENTATION_PORTRAIT");
			}

			else if (display.getRotation() == Surface.ROTATION_90
					&& rotation == Configuration.ORIENTATION_LANDSCAPE) {
				parameters.setPreviewSize(w, h);
				parameters.setRotation(0);
				camera.setDisplayOrientation(0);
				Log.d("TAG", "Surface.ROTATION_90 - ORIENTATION_LANDSCAPE");
			} else if (display.getRotation() == Surface.ROTATION_270
					&& rotation == Configuration.ORIENTATION_LANDSCAPE) {
				parameters.setPreviewSize(w, h);
				parameters.setRotation(180);
				camera.setDisplayOrientation(180);
				Log.d("TAG", "Surface.ROTATION_270 - ORIENTATION_PORTRAIT");
			}
			camera.setParameters(parameters);
			camera.startPreview();
		} catch (Exception e) {
		}
	}

	private Bitmap rotateBitmap(YuvImage yuvImage, int orientation,
			Rect rectangle) {
		ByteArrayOutputStream os = new ByteArrayOutputStream();
		yuvImage.compressToJpeg(rectangle, TTCameraConstant.CAMERA_QUALITY, os);

		Matrix matrix = new Matrix();
		matrix.postRotate(orientation);
		byte[] bytes = os.toByteArray();
		Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
		return Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(),
				bitmap.getHeight(), matrix, true);
	}

	@Override
	public void surfaceDestroyed(SurfaceHolder holder) {
		// TODO Auto-generated method stub

	}

}

/*
 * Display display = ((Activity) mContext).getWindowManager()
 * .getDefaultDisplay(); int w = previewSize.width; int h = previewSize.height;
 * int rotation = mContext.getResources().getConfiguration().orientation;
 * Log.i("TAG", "screen rotation is " + rotation); Log.i("TAG",
 * "display rotation is " + display.getRotation());
 * 
 * if (display.getRotation() == Surface.ROTATION_0) { if (rotation ==
 * Configuration.ORIENTATION_LANDSCAPE) { parameters.setPreviewSize(h, w);
 * parameters.setRotation(0); camera.setDisplayOrientation(0); Log.d("TAG",
 * "Surface.ROTATION_0 - ORIENTATION_LANDSCAPE"); } else { Log.d("TAG",
 * "Surface.ROTATION_0 - ORIENTATION_PORTRAIT"); parameters.setPreviewSize(h,
 * w); parameters.setRotation(270); camera.setDisplayOrientation(90); } }
 * 
 * else if (display.getRotation() == Surface.ROTATION_90) { if (rotation ==
 * Configuration.ORIENTATION_PORTRAIT) { parameters.setPreviewSize(w, h);
 * parameters.setRotation(90); camera.setDisplayOrientation(270); Log.d("TAG",
 * "Surface.ROTATION_90 - ORIENTATION_PORTRAIT"); } else { Log.d("TAG",
 * "Surface.ROTATION_90 - ORIENTATION_LANDSCAPE"); parameters.setPreviewSize(w,
 * h); parameters.setRotation(90); camera.setDisplayOrientation(270); } }
 * 
 * else if (display.getRotation() == Surface.ROTATION_180) { if (rotation ==
 * Configuration.ORIENTATION_LANDSCAPE) { parameters.setPreviewSize(h, w);
 * parameters.setRotation(180); camera.setDisplayOrientation(180); Log.d("TAG",
 * "Surface.ROTATION_180 - ORIENTATION_PORTRAIT"); } else { Log.d("TAG",
 * "Surface.ROTATION_180 - ORIENTATION_LANDSCAPE"); parameters.setPreviewSize(h,
 * w); parameters.setRotation(90); camera.setDisplayOrientation(270); } }
 * 
 * else if (display.getRotation() == Surface.ROTATION_270) { if (rotation ==
 * Configuration.ORIENTATION_PORTRAIT) { parameters.setPreviewSize(w, h);
 * parameters.setRotation(270); camera.setDisplayOrientation(90); Log.d("TAG",
 * "Surface.ROTATION_270 - ORIENTATION_PORTRAIT"); } else { Log.d("TAG",
 * "Surface.ROTATION_270 - ORIENTATION_LANDSCAPE"); parameters.setPreviewSize(w,
 * h); parameters.setRotation(180); camera.setDisplayOrientation(180); } }
 * camera.setParameters(parameters);
 */